iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 7
0
自我挑戰組

圖解Javascript面試題目30天系列 第 7

Day 07 Function是什麼?能吃嗎? (6) Closures & Scope

  • 分享至 

  • xImage
  •  

「錢包沒事不要打開,不然會散財」 之 「不讓變數外露的閉包」

閉包這個題目,真的有點難...
不過還是讓我們來嘗試看看吧!!

27. What are closures 什麼是閉包?

A closure is the combination of a function and the lexical environment within which that function was declared. i.e, It is an inner function that has access to the outer or enclosing function’s variables. The closure has three scope chains

  1. Own scope where variables defined between its curly brackets
  2. Outer function’s variables
  3. Global variables

@翻譯翻譯

閉包是指一個函式及此函式宣告的語彙環境的組合。亦即閉包是一個可以存取外部函式的變數的內部函式。閉包有三個範疇鍊(作用域):

  1. 函式自身的作用域(花括弧中的部分)
  2. 外部函式的變數
  3. 全域變數

30. What is scope in JavaScript 什麼是範疇?(作用域)

Scope is the accessibility of variables, functions, and objects in some particular part of your code during runtime. In other words, scope determines the visibility of variables and other resources in areas of your code.

@翻譯翻譯

作用域描述了在程式的執行階段中,一段特定的程式碼中的變數、函式、或者物件,是否可被存取。換句話說,作用域決定了在特定的程式區塊中,變數或者資源是否能被抓到(caught)。

無法被抓到就會出現Uncaught ReferenceError: _ is not defined (´A` )有沒有很熟悉


以函式為例,在其中生成的變數,只能在其中生存,離開這個環境後就會被釋放(從外部存取不到)。

const saySomethingTo = (name) => {
  let message = `Good night,`
  console.log(`${message} ${name}`)
}

saySomethingTo('Leo') // "Good night, Leo"
console.log(message) // Uncaught ReferenceError: message is not defined

而閉包就是利用作用域這個特性,來達成一個效果:

把變數藏在函式裡面,讓外部無法直接存取,只能透過執行函式來存取這個變數,以至於這個變數無法被任意修改,而且這個變數不會被釋放,以至於可以重複使用。

是不是還是一頭霧水呢(ಠ益ಠ)?先讓我們來看看下面的範例吧!

範例

// 1. 原本的函式
var leftFood = 3000
var income = 0
function sellFood(n) {
  leftFood -= n 
  income += n*10 
}

sellFood(100) 
console.log(leftFood) // 2900,賣掉100個食物,剩下2900個
console.log(income) // 1000,一個食物10元,總收入1000元

leftFood -= 200
console.log(leftFood) // 2700,被偷走200個食物
console.log(income) // 1000,因為是被偷走的,所以收入沒增加

// 2. 運用閉包的特性改寫
function restaurant() {
  var leftFood = 3000
  var income = 0
  return {
    sellFood: (n) => {
      leftFood -= n 
      income += n*10
      console.log(leftFood)
      console.log(income)
    }
  }
}
var myRestaurant = restaurant()
myRestaurant.sellFood(100) // 2900, 1000 賣100個食物,總收入1000元
myRestaurant.sellFood(100) // 2800, 2000 再賣100個食物,總收入2000元
leftFood -= 200 // Uncaught ReferenceError: leftFood is not defined 偷不到食物了!

@翻譯翻譯:

在第一個函式中,我們可以透過執行sellFood(n)來讓變數依照我們的規則做改變,在此範例中,就是:賣出食物,就會有收入。但是因為變數裸露在外,所以是可以直接對其做修改的!(leftFood -= 200)若真的發生這樣的事,餐廳的帳就會對不起來啦ˊ_ゝˋ

而第二個函式,我們把變數藏在restaurant()裡面,並且令其回傳一個「物件」,內含一個keysellFood的函式。如此一來,若要在外部存取這個物件運用到的變數,只要透過restaurant()去執行它所回傳的這個函式即可。

var myRestaurant = restaurant()
myRestaurant.sellFood(100)

若試圖從外部直接存取leftFood,也僅僅會得到Uncaught ReferenceError而已。
這樣食物就不會被偷走啦~~


今天用到的範例有物件的概念,明天開始我們來看看「Object」在JavaScript之中是怎麼樣的一回事吧!和function比較直接相關的面試問題,就先分享到這邊囉~~

若有什麼錯誤,還請不吝留言指正~~謝謝各位願意來看我的文章(被荼毒的話真的很抱歉。゚ヽ(゚´Д`)ノ゚。)


後記:

因為閉包這個概念真的太難解釋了,所以我同時參考了國內幾個大大的文章,其中這一篇寫得非常明白,連身為菜雞的我也能看得懂幾成。推薦大家可以把它看完:)


上一篇
Day 06 Function是什麼?能吃嗎? (5) Pure Function
下一篇
Day 08 JavaScript之——你有聽過「物件」嗎? (1) Intro
系列文
圖解Javascript面試題目30天9
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言